#region Using Directives

using System;
using System.Runtime.InteropServices;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

#endregion Using Directives

namespace SharePointStu.ItemAuditing.Features.Item_Level_Auditing
{
    /// <summary>
    /// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.
    /// </summary>
    /// <remarks>
    /// The GUID attached to this class may be used during packaging and should not be modified.
    /// </remarks>
    [Guid("4b07b155-610e-4ed0-983b-717a20b8cb82")]
    public class Item_Level_AuditingEventReceiver : SPFeatureReceiver
    {
        #region Inner Class

        public class AuditSettings : SPPersistedObject
        {
            protected override bool HasAdditionalUpdateAccess()
            {
                return true;
            }

            #region Constants

            const string AUDIT_SETTINGS_PERSISTED_NAME = "SharePointStu.AuditSettings";

            #endregion Constants

            #region Persisted Members

            [Persisted]
            SPAuditMaskType _auditFlags;

            #endregion Persisted Members

            #region Constructors

            public AuditSettings()
            {
                _auditFlags = SPAuditMaskType.None;
            }

            public AuditSettings(string name, SPPersistedObject parent, Guid id, SPAuditMaskType mask)
                : base(name, parent, id)
            {
                _auditFlags = mask;
            }

            #endregion Constructors

            #region Public Properties

            /// <summary>
            /// Get or set the SPAuditMaskType flags.
            /// </summary>
            public SPAuditMaskType AuditFlags
            {
                get { return _auditFlags; }
                set { _auditFlags = value; }
            }

            #endregion Public Properties

            #region Public Methods

            /// <summary>
            /// Get the name for persisted object in relation to the owning object.
            /// </summary>
            /// <param name="identifier">Identifier of parent object.</param>
            /// <returns>Name for persisted object.</returns>
            public static string GetName(Guid identifier)
            {
                return string.Concat(AUDIT_SETTINGS_PERSISTED_NAME, "_", identifier);
            }

            #endregion Public Methods
        }

        #endregion Inner Class

        #region Overridden Methods

        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            SPSite site = properties.Feature.Parent as SPSite;
            SPWeb web = null;
            if (site != null)
            {
                web = site.RootWeb;
            }
            else
            {
                web = properties.Feature.Parent as SPWeb;
            }

            Guid siteId = web.Site.ID;
            SPSecurity.RunWithElevatedPrivileges(()=>
            {
                using (SPSite elevatedSite = new SPSite(siteId))
                {
                    AuditSettings auditSettings = elevatedSite.WebApplication.GetChild<AuditSettings>(AuditSettings.GetName(siteId));
                    if (auditSettings == null)
                    {
                        SPPersistedObject parent = elevatedSite.WebApplication;
                        auditSettings = new AuditSettings(AuditSettings.GetName(siteId), parent, Guid.NewGuid(), elevatedSite.Audit.AuditFlags);

                        try
                        {
                            auditSettings.Update();
                        }
                        catch
                        {
                            // suppress error, depending on your enviornment the above line may generate an error, so for the sake of easiness and to get it to deploy
                            // we're going to ignore it for the time being.
                        }
                    }
                    elevatedSite.Audit.AuditFlags = SPAuditMaskType.All;
                    elevatedSite.Audit.Update();
                }
            });
        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            SPSite site = properties.Feature.Parent as SPSite;
            SPWeb web = null;
            if (site != null)
            {
                web = site.RootWeb;
            }
            else
            {
                web = properties.Feature.Parent as SPWeb;
            }

            Guid siteId = web.Site.ID;
            SPSecurity.RunWithElevatedPrivileges(()=>
            {
                using (SPSite elevatedSite = new SPSite(siteId))
                {
                    AuditSettings auditSettings = elevatedSite.WebApplication.GetChild<AuditSettings>(AuditSettings.GetName(siteId));
                    if (auditSettings != null)
                    {
                        try
                        {
                            elevatedSite.Audit.AuditFlags = auditSettings.AuditFlags;
                            elevatedSite.Audit.Update();

                            auditSettings.Uncache();
                            auditSettings.Unprovision();
                            auditSettings.Delete();
                        }
                        catch
                        {
                            // As with above method
                        }
                    }
                }
            });
        }

        public override void FeatureInstalled(SPFeatureReceiverProperties properties) { }

        public override void FeatureUninstalling(SPFeatureReceiverProperties properties) { }

        #endregion Overridden Methods
    }
}
